记一次对请求头为multipartform 您所在的位置:网站首页 gateway 加解密 记一次对请求头为multipartform

记一次对请求头为multipartform

2024-01-09 02:34| 来源: 网络整理| 查看: 265

记一次对请求头为multipart/form-data的post请求参数加密操作以及传参

背景:对接一个第三方系统,提供的接口要求对参数进行RSA加密,Base64转码。而且请求头为multipart/form-data。

1、秘钥加密代码 /** *

* 私钥加密 *

* * @param data * 源数据 * @param privateKey * 私钥(BASE64编码) * @return * @throws Exception */ public static byte[] encryptByPrivateKey(byte[] data, String privateKey) throws Exception { byte[] keyBytes = Base64.decodeBase64(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key priKey = keyFactory.generatePrivate(pkcs8KeySpec); return decryptOrEncrypt(data, keyFactory, priKey, Cipher.ENCRYPT_MODE, MAX_ENCRYPT_BLOCK); } /** * 对数据进行解密/加密过程 * * @param data 已加密数据 * @param keyFactory key工厂 * @param key key(pub/pri) * @param model 加解密模式 * @return * @throws Exception */ private static byte[] decryptOrEncrypt(byte[] data, KeyFactory keyFactory, Key key, int model, int block) throws Exception { Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(model, key); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 对数据分段解密 while (inputLen - offSet > 0) { if (inputLen - offSet > block) { cache = cipher.doFinal(data, offSet, block); } else { cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * block; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } 2、Base64转码

使用的是org.apache.commons.codec.binary包下的Base64

public static String encodeBase64String(byte[] binaryData) { return StringUtils.newStringUsAscii(encodeBase64(binaryData, false)); } 3、签名MD5加密 /** *@param str1 加密方式 *@param str2 需加密字符串 */ private static String digest(String str1, String str2) { try { byte[] Data = str2.getBytes(); MessageDigest Cdigest = MessageDigest.getInstance(str1); Cdigest.update(Data); // MD5直 --dig byte[] dig = Cdigest.digest(); // PrintByteArray("dig", dig); // byte []形式表达的MD5 转化为 16H形式String表达的MD5 String str16hMD5 = bytesToHexString(dig); return str16hMD5; } catch (Exception e) { return null; } } 4、请求头为multipart/form-data,参数需要特殊处理 a.获取连接对象 /** * 获得连接对象 * * @param urlStr * @param headers * @return * @throws IOException */ private static HttpURLConnection getHttpURLConnection(String urlStr, Map headers) throws IOException { URL url = new URL(urlStr); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //设置超时时间 conn.setConnectTimeout(50000); conn.setReadTimeout(50000); //允许输入流 conn.setDoInput(true); //允许输出流 conn.setDoOutput(true); //不允许使用缓存 conn.setUseCaches(false); //请求方式 conn.setRequestMethod("POST"); //设置编码 utf-8 conn.setRequestProperty("Charset", "UTF-8"); //设置为长连接 conn.setRequestProperty("connection", "keep-alive"); //设置其他自定义 headers if (headers != null && !headers.isEmpty()) { for (Map.Entry header : headers.entrySet()) { conn.setRequestProperty(header.getKey(), header.getValue().toString()); } } return conn; }

b、写文件类型的表单参数

/** * 写文件类型的表单参数 * * @param paramName 参数名 * @param filePath 文件路径 * @param boundary 分隔符 * @param out * @throws IOException */ private static void writeFile(String paramName, String filePath, String boundary, DataOutputStream out) { try (BufferedReader fileReader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath)))) { /** * 写分隔符--${boundary},并回车换行 */ String boundaryStr = BOUNDARY_PREFIX + boundary + LINE_END; out.write(boundaryStr.getBytes()); /** * 写描述信息(文件名设置为上传文件的文件名): * 写 Content-Disposition: form-data; name="参数名"; filename="文件名",并回车换行 * 写 Content-Type: application/octet-stream,并两个回车换行 */ String fileName = new File(filePath).getName(); String contentDispositionStr = String.format("Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"", paramName, fileName) + LINE_END; out.write(contentDispositionStr.getBytes()); String contentType = "Content-Type: application/octet-stream" + LINE_END + LINE_END; out.write(contentType.getBytes()); String line; while ((line = fileReader.readLine()) != null) { out.write(line.getBytes()); } //回车换行 out.write(LINE_END.getBytes()); } catch (Exception e) { LOGGER.error("写文件类型的表单参数异常", e); } }

c、写普通的表单参数

/** * 写普通的表单参数 * * @param boundary 分隔符 * @param out * @param entry 参数的键值对 * @throws IOException */ private static void writeSimpleFormField(String boundary, DataOutputStream out, Map.Entry entry) throws IOException { //写分隔符--${boundary},并回车换行 String boundaryStr = BOUNDARY_PREFIX + boundary + LINE_END; out.write(boundaryStr.getBytes()); //写描述信息:Content-Disposition: form-data; name="参数名",并两个回车换行 String contentDispositionStr = String.format("Content-Disposition: form-data; name=\"%s\"", entry.getKey()) + LINE_END + LINE_END; out.write(contentDispositionStr.getBytes()); //写具体内容:参数值,并回车换行 String valueStr = entry.getValue().toString() + LINE_END; out.write(valueStr.getBytes()); }

d、请求

/** * * @param url 请求路径 * @param filePathMap 文件参数 * @param keyValues 普通参数 * @return 请求结果 */ public static String postFormData(String url,Map filePathMap,Map keyValues) { LOGGER.info("发起http请求的url:{}",url); LOGGER.info("文件请求参数filePathMap:{}",filePathMap); LOGGER.info("文本参数keyValues:{}",keyValues); StringBuffer buffer = new StringBuffer(); HttpURLConnection con = null; try { con = getHttpURLConnection(url, null); } catch (IOException e) { e.printStackTrace(); } //分隔符,可以任意设置,这里设置为 MyBoundary+ 时间戳(尽量复杂点,避免和正文重复) String boundary = "MyBoundary" + System.currentTimeMillis(); //设置 Content-Type 为 multipart/form-data; boundary=${boundary} con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); //发送参数数据 try (DataOutputStream out = new DataOutputStream(con.getOutputStream())) { //发送普通参数 if (keyValues != null && !keyValues.isEmpty()) { for (Map.Entry entry : keyValues.entrySet()) { writeSimpleFormField(boundary, out, entry); } } //发送文件类型参数 if (filePathMap != null && !filePathMap.isEmpty()) { for (Map.Entry filePath : filePathMap.entrySet()) { writeFile(filePath.getKey(), filePath.getValue(), boundary, out); } } //写结尾的分隔符--${boundary}--,然后回车换行 String endStr = BOUNDARY_PREFIX + boundary + BOUNDARY_PREFIX + LINE_END; out.write(endStr.getBytes()); out.flush(); out.close(); if (con.getResponseCode() == 200) { InputStream in = con.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(in, "utf-8")); String temp; while ((temp = br.readLine()) != null) { buffer.append(temp); // buffer.append("\n"); } in.close(); br.close(); } } catch (Exception e) { LOGGER.error("HttpUtils.postFormData 请求异常!", e); } LOGGER.info("http请求相应数据:{}", buffer.toString()); return buffer.toString(); } 5、根据业务场景调用方法 public String enrollAdd(EnrollAddVO vo){ Map map = new HashMap(4); JSONObject requestObj = new JSONObject(); requestObj.put("name",vo.getName()); requestObj.put("sex",vo.getSex()); byte[] requestString = null; try { requestString = RsaUtils.encryptByPrivateKey(requestObj.toJSONString().getBytes("UTF-8"),RAS_KEY); }catch (Exception e){ log.info("RSA加密失败:{}",e.getMessage()); } String base64Str = Base64.encodeBase64String(requestString); String sign = MD5Util.genMD5(base64Str + SECRET_KEY); map.put("appKey",APP_KEY); map.put("request",base64Str); map.put("sign",sign); return HttpClientUtil.postFormData(ENROLL_ADD_URL,null,map); }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有